home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1996 May: Tool Chest / Developer CD Series May 1996 (Tool Chest) (Apple Computer) (1996).iso / Sample Code / Snippets / Sound / GiMeDaPalette w⁄Sound / GiMeDaPalette&Sound.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-02-11  |  17.9 KB  |  650 lines  |  [TEXT/MPS ]

  1. /*______________________________________________________*/
  2. /*                       Palette Demo                        */
  3. /*                          by                          */
  4. /*                  RICHARD P. COLLYER                  */
  5. /*              Developer Technical Support             */
  6. /*                 Apple Computer, Inc.                 */
  7. /*                       08/15/90                       */
  8. /*______________________________________________________*/
  9.  
  10. #include    <CType.h>
  11. #include    <Quickdraw.h>
  12. #include    <Windows.h>
  13. #include    <desk.h>
  14. #include    <dialogs.h>
  15. #include    <Events.h>
  16. #include     <GestaltEqu.h>
  17. #include    <Memory.h>
  18. #include    <Menus.h>
  19. #include    <OSEvents.h>
  20. #include    <Palettes.h>
  21. #include    <SegLoad.h>
  22. #include    <Sound.h>
  23. #include    <Resources.h>
  24. #include    <ToolUtils.h>
  25. #include    <StdIO.h>
  26. #include    <QDOffscreen.h>
  27.  
  28. extern _DataInit();
  29.  
  30. #define pmInhibitG2        0x0100
  31. #define pmInhibitC2        0x0200
  32. #define pmInhibitG4        0x0400
  33. #define pmInhibitC4        0x0800
  34. #define pmInhibitG8        0x1000
  35. #define pmInhibitC8        0x2000
  36.  
  37. #define    TRUE            0xFF
  38. #define    FALSE            0
  39. #define Gestalttest        0xA1AD
  40. #define NoTrap            0xA89F
  41.  
  42. #define    appleID            128            
  43. #define    appleMenu        0
  44. #define    aboutMeCommand    1
  45.  
  46. #define    fileID            129
  47. #define    quitCommand     1
  48.  
  49. #define    PaletteID        130
  50. #define    CourCommand     1
  51. #define    TolCommand         2
  52. #define    ExpCommand         3
  53. #define    AniCommand         4
  54. #define    TolExpCommand     6
  55. #define    TolAniCommand     7
  56. #define    ExpAniCommand     8
  57. #define    TEACommand         10
  58.  
  59. #define    PictID            128
  60. #define    clutID            150
  61.  
  62. #define    aboutMeDLOG        128
  63. #define    okButton        1
  64. #define    authorItem        2
  65. #define    languageItem    3
  66. #define    numcolor        256
  67.  
  68. #define kDoubleBufferSize    0x1000
  69.  
  70. struct LocalVars {
  71.     long    bytesTotal;
  72.     long    bytesCopied;
  73.     Ptr        dataPtr;
  74. };
  75.  
  76. typedef struct LocalVars LocalVars;
  77. typedef LocalVars *LocalVarsPtr;
  78.  
  79. Rect                    TotalRect, minRect, WinMinusScroll, InitWindowSize;
  80. WindowPtr                myWindow;
  81. CTabHandle                mycolors;
  82. PaletteHandle            srcPalette;
  83. Boolean                    DoneFlag;
  84. MenuHandle                mymenu1, mymenu2, mymenu0;
  85. PicHandle                ThePict;
  86. GWorldPtr                offscreenGWorld;
  87. SndDoubleBufferHeader    doubleHeader;
  88. SndDoubleBufferPtr        doubleBuffer;
  89. SCStatus                Stats;
  90. SndChannelPtr            chan;
  91. SoundHeaderPtr            Head;
  92. Handle                    SoundData;
  93. LocalVars                myVars;
  94. SndDoubleBackUPP        gSndDoubleBackUPP;
  95.  
  96.  
  97. #ifdef powerc
  98.    QDGlobals    qd;
  99. #endif
  100.  
  101. pascal void MyDoubleBackProc (SndChannelPtr channel, SndDoubleBufferPtr doubleBufferPtr);
  102.  
  103. /*______________________________________________________*/
  104. /*              Sound Double Back Proc                  */
  105. /*______________________________________________________*/
  106. pascal void MyDoubleBackProc (SndChannelPtr chan,SndDoubleBufferPtr doubleBuffer)
  107. {
  108. LocalVarsPtr    myVarsPtr;
  109. long            bytesToCopy;
  110.  
  111. myVarsPtr = (LocalVarsPtr) doubleBuffer->dbUserInfo[0];
  112. bytesToCopy = myVarsPtr->bytesTotal - myVarsPtr->bytesCopied;
  113.  
  114. if (bytesToCopy > kDoubleBufferSize)
  115.     bytesToCopy = kDoubleBufferSize;
  116.     
  117. BlockMove (myVarsPtr->dataPtr, &doubleBuffer->dbSoundData[0], bytesToCopy);
  118.  
  119. doubleBuffer->dbNumFrames = bytesToCopy;
  120. doubleBuffer->dbFlags = (doubleBuffer->dbFlags) | dbBufferReady;
  121.  
  122. myVarsPtr->dataPtr = (Ptr) ((myVarsPtr->dataPtr) + bytesToCopy);
  123. myVarsPtr->bytesCopied = myVarsPtr->bytesCopied + bytesToCopy;
  124.  
  125. if (myVarsPtr->bytesCopied == myVarsPtr->bytesTotal) {
  126.     doubleBuffer->dbFlags = (doubleBuffer->dbFlags) | dbLastBuffer;
  127.     }
  128.     
  129. return;
  130. }
  131.  
  132. /*______________________________________________________*/
  133. /*                Check Correct Menu                    */
  134. /*______________________________________________________*/
  135. void CheckMenu(int whichMenu)
  136. /* This procedure checks and unchecks the appropriate menus */
  137. {
  138.             CheckItem(mymenu2,CourCommand,FALSE);
  139.             CheckItem(mymenu2,TolCommand,FALSE);
  140.             CheckItem(mymenu2,ExpCommand,FALSE);
  141.             CheckItem(mymenu2,AniCommand,FALSE);
  142.             CheckItem(mymenu2,TolExpCommand,FALSE);
  143.             CheckItem(mymenu2,TolAniCommand,FALSE);
  144.             CheckItem(mymenu2,ExpAniCommand,FALSE);
  145.             CheckItem(mymenu2,TEACommand,FALSE);
  146.     switch (whichMenu) {
  147.         case CourCommand:
  148.             CheckItem(mymenu2,CourCommand,TRUE);
  149.             break;
  150.         case TolCommand:
  151.             CheckItem(mymenu2,TolCommand,TRUE);
  152.             break;
  153.         case ExpCommand:
  154.             CheckItem(mymenu2,ExpCommand,TRUE);
  155.             break;
  156.         case AniCommand:
  157.             CheckItem(mymenu2,AniCommand,TRUE);
  158.             break;
  159.         case TolExpCommand:
  160.             CheckItem(mymenu2,TolExpCommand,TRUE);
  161.             break;
  162.         case TolAniCommand:
  163.             CheckItem(mymenu2,TolAniCommand,TRUE);
  164.             break;
  165.         case ExpAniCommand:
  166.             CheckItem(mymenu2,ExpAniCommand,TRUE);
  167.             break;
  168.         case TEACommand:
  169.             CheckItem(mymenu2,TEACommand,TRUE);
  170.             break;
  171.         defalut:
  172.             break;
  173.         }
  174. }
  175.  
  176. /*______________________________________________________*/
  177. /*                     Start Sound                      */
  178. /*______________________________________________________*/
  179. void SoundSetUp()
  180. {
  181.     int                i;
  182.     OSErr            err;
  183.     
  184.     chan = nil;
  185.     err = SndNewChannel (&chan, sampledSynth, 0, nil);
  186.     if (err != noErr)
  187.         Debugger();
  188.     
  189.     Head = (SoundHeaderPtr) NewPtrClear (sizeof(SoundHeader));
  190.     Head->samplePtr = *SoundData;
  191.     Head->length = 45838;
  192.     Head->sampleRate = 0x56EE8BA3;        //recorded at 22KHz
  193.     Head->loopStart = 0;
  194.     Head->loopEnd = 0;
  195.     Head->encode = 0;
  196.     Head->baseFrequency = 60;
  197.     Head->sampleArea[0] = 0;
  198.  
  199.     myVars.bytesTotal = Head->length;
  200.     myVars.bytesCopied = 0;
  201.     myVars.dataPtr = Head->samplePtr;
  202.  
  203.     doubleHeader.dbhNumChannels = 1;
  204.     doubleHeader.dbhSampleSize = 8;
  205.     doubleHeader.dbhCompressionID = 0;
  206.     doubleHeader.dbhPacketSize = 0;
  207.     doubleHeader.dbhSampleRate = Head->sampleRate;
  208.     
  209.     doubleHeader.dbhDoubleBack = gSndDoubleBackUPP;
  210.  
  211.     for (i = 0; i <= 1; ++i) {
  212.         doubleBuffer = (SndDoubleBufferPtr) NewPtrClear (sizeof(SndDoubleBuffer) + kDoubleBufferSize);
  213.     
  214.         if (doubleBuffer == nil || MemError() != 0)
  215.             Debugger();
  216.         
  217.         doubleBuffer->dbNumFrames = 0;
  218.         doubleBuffer->dbFlags = 0;
  219.         doubleBuffer->dbUserInfo [0] = (long) &myVars;
  220.     
  221.         MyDoubleBackProc (chan, doubleBuffer);            // initialize the buffers
  222.     
  223.         doubleHeader.dbhBufferPtr [i] = doubleBuffer;
  224.         }
  225. }
  226.  
  227. /*______________________________________________________*/
  228. /*                     Start Sound                      */
  229. /*______________________________________________________*/
  230. void SoundOff()
  231. {
  232.     OSErr        err;
  233.     
  234.     err = SndPlayDoubleBuffer (chan, &doubleHeader);
  235.     if (err != noErr)
  236.         Debugger();
  237. }
  238.  
  239. /*______________________________________________________*/
  240. /*             Set Up Usage of Palette                  */
  241. /*______________________________________________________*/
  242. void Draw()
  243. {
  244.     RGBColor        black = {0,0,0}, White = {65535,65535,65535};
  245.         
  246.     RGBForeColor (&black);
  247.     RGBBackColor (&White);
  248.     CopyBits ((BitMap *) *offscreenGWorld->portPixMap, &myWindow->portBits, 
  249.                     &InitWindowSize, &WinMinusScroll, srcCopy, nil);
  250. }
  251.  
  252. /*______________________________________________________*/
  253. /*             Set Up Usage of Palette                  */
  254. /*______________________________________________________*/
  255. void SetInhibited(int Usage)
  256. /* When the usage of the palette changes I need to rebuild the palette,
  257. so I call this routine.  I need to call SetEntryUsage on all of the entries
  258. of the palette, but I want to make sure that if the monitor is set to a bit depth
  259. low than 8 bits that the palette is limited in its colors.  So the first two colors
  260. (not including white) are set to work at all depths except 1 bit mode.  The next 
  261. 12 entries are set to work on all depths except 1 & 2 bit modes.  The rest of 
  262. the colors are set to only work in 8 bit mode.  I have also set the tolerance to
  263. hex 1500.  With this tolerance I will be able to get most of the colors I need 
  264. and those that I don't get exact will be very close. */
  265. {
  266.     int        i;
  267.     
  268.     CTab2Palette (mycolors, srcPalette, Usage, 0x1500);
  269.     for (i = 1; i <= 2; ++i) {
  270.         SetEntryUsage (srcPalette, i, Usage, 0x1500);
  271.         }
  272.     for (i = 3; i <= 14; ++i) {
  273.         SetEntryUsage (srcPalette, i, Usage+pmInhibitG2+pmInhibitC2, 0x1500);
  274.         }
  275.     for (i = 15; i < numcolor; ++i) {
  276.         SetEntryUsage (srcPalette, i, Usage+pmInhibitG2+pmInhibitC2+
  277.                         pmInhibitG4+pmInhibitC4, 0x1500);
  278.         }
  279. }
  280.  
  281. /*______________________________________________________*/
  282. /*                 About Prog Dialog                    */
  283. /*______________________________________________________*/
  284. void showAboutMeDialog()
  285. {
  286.     GrafPtr     savePort;
  287.     DialogPtr    theDialog;
  288.     short        itemHit;
  289.  
  290.     GetPort(&savePort);
  291.     theDialog = GetNewDialog(aboutMeDLOG, nil, (WindowPtr) -1);
  292.     SetPort(theDialog);
  293.  
  294.     do {
  295.         ModalDialog(nil, &itemHit);
  296.     } while (itemHit != okButton);
  297.  
  298.     CloseDialog(theDialog);
  299.  
  300.     SetPort(savePort);
  301.     return;
  302. }
  303.  
  304. /*______________________________________________________*/
  305. /*                 Do Menu Function                     */
  306. /*______________________________________________________*/
  307. void doCommand(mResult)
  308.     long    mResult;
  309. {
  310.     int                     theMenu, theItem;
  311.     char                    daName[256];
  312.     GrafPtr                 savePort;
  313.  
  314.     theItem = LoWord(mResult);
  315.     theMenu = HiWord(mResult);
  316.     
  317.     switch (theMenu) {
  318. /*______________________________________________________*/
  319. /*                    Do Apple Menu                     */
  320. /*______________________________________________________*/
  321.         case appleID:
  322.             if (theItem == aboutMeCommand)
  323.                 showAboutMeDialog();
  324.             else {
  325.                 GetMenuItemText(mymenu0, theItem, daName);
  326.                 GetPort(&savePort);
  327.                 (void) OpenDeskAcc(daName);
  328.                 SetPort(savePort);
  329.             }
  330.             break;
  331. /*______________________________________________________*/
  332. /*                     Do File Menu                     */
  333. /*______________________________________________________*/
  334.         case fileID:
  335.             switch (theItem) {
  336.                 case quitCommand:
  337.                     DoneFlag = TRUE;
  338.                     break;
  339.                 default:
  340.                     break;
  341.                 }
  342.             break;
  343.  
  344. /*______________________________________________________*/
  345. /*                     Do File Menu                     */
  346. /*______________________________________________________*/
  347.         case PaletteID:
  348.             switch (theItem) {
  349.                 case CourCommand:
  350.                     CheckMenu(CourCommand);
  351.                     SetInhibited(pmCourteous);
  352.                     break;
  353.                 case TolCommand:
  354.                     CheckMenu(TolCommand);
  355.                     SetInhibited(pmTolerant);
  356.                     break;
  357.                 case ExpCommand:
  358.                     CheckMenu(ExpCommand);
  359.                     SetInhibited(pmExplicit);
  360.                     break;
  361.                 case AniCommand:
  362.                     CheckMenu(AniCommand);
  363.                     SetInhibited(pmAnimated);
  364.                     SoundOff();
  365.                     break;
  366.                 case TolExpCommand:
  367.                     CheckMenu(TolExpCommand);
  368.                     SetInhibited(pmTolerant+pmExplicit);
  369.                     break;
  370.                 case TolAniCommand:
  371.                     CheckMenu(TolAniCommand);
  372.                     SetInhibited(pmTolerant+pmAnimated);
  373.                     SoundOff();
  374.                     break;
  375.                 case ExpAniCommand:
  376.                     CheckMenu(ExpAniCommand);
  377.                     SetInhibited(pmAnimated+pmExplicit);
  378.                     SoundOff();
  379.                     break;
  380.                 case TEACommand:
  381.                     CheckMenu(TEACommand);
  382.                     SetInhibited(pmTolerant+pmExplicit+pmAnimated);
  383.                     SoundOff();
  384.                     break;
  385.                 default:
  386.                     break;
  387.                 }
  388.             SetPalette ((WindowPtr) myWindow, srcPalette, TRUE);
  389.             ActivatePalette ((WindowPtr) myWindow);
  390.             break;
  391.         }
  392.     HiliteMenu(0);
  393.     return;
  394. }
  395.  
  396.  
  397. /*______________________________________________________*/
  398. /*               Initialization traps                   */
  399. /*______________________________________________________*/
  400. void init()
  401. {
  402.     RgnHandle            tempRgn;
  403.     Rect                BaseRect;
  404.     OSErr                err;
  405.     long                QDfeature, OSfeature;
  406.     GDHandle            SaveGD;
  407.     CGrafPtr            SavePort;
  408.     RGBColor            black = {0,0,0}, White = {65535,65535,65535};
  409.  
  410.     UnloadSeg(_DataInit);
  411.     InitGraf(&qd.thePort);
  412.     FlushEvents(everyEvent, 0);
  413.     InitWindows();
  414.     InitDialogs(nil);
  415.     InitCursor();
  416.     
  417.     /* set up the UPP for MyDoubleBackProc */
  418.     gSndDoubleBackUPP = NewSndDoubleBackProc(MyDoubleBackProc);
  419.     
  420.     DoneFlag = FALSE;
  421.     ThePict = GetPicture(PictID);
  422.     if (ThePict == nil)
  423.         DoneFlag = TRUE;
  424.  
  425. /*______________________________________________________*/
  426. /*            Use Gestalt to find 32BQD                 */
  427. /*______________________________________________________*/
  428.     err = Gestalt(gestaltQuickdrawVersion, &QDfeature);
  429.     if (err && (QDfeature & 0x0f00) < 0x0200)
  430.         DoneFlag = TRUE;
  431.     err = Gestalt(gestaltSystemVersion, &OSfeature);
  432.     if (err)
  433.         DoneFlag = TRUE;
  434.     if (!DoneFlag && (QDfeature & 0x0f00) != 0x0200 && OSfeature < 0x0605)
  435.         DoneFlag = TRUE;
  436. /*______________________________________________________*/
  437. /*                     Set Rects                        */
  438. /*______________________________________________________*/
  439. if (DoneFlag == FALSE) {
  440.     SetRect(&BaseRect, 40, 60, 472, 282);
  441.     SetRect(&WinMinusScroll, BaseRect.left-40, BaseRect.top-60, BaseRect.right-60, 
  442.                 BaseRect.bottom - 80);
  443.     SetRect(&InitWindowSize, WinMinusScroll.left, WinMinusScroll.top, 
  444.                             WinMinusScroll.right, WinMinusScroll.bottom);
  445.     tempRgn = GetGrayRgn();
  446.     HLock ((Handle) tempRgn);
  447.     TotalRect = (**tempRgn).rgnBBox;
  448.     SetRect(&minRect, 80, 80, (**tempRgn).rgnBBox.right - 40, 
  449.                 (**tempRgn).rgnBBox.bottom - 40);
  450.     HUnlock ((Handle) tempRgn);
  451.  
  452. /*______________________________________________________*/
  453. /*        Open Window & set Palette & Picture           */
  454. /*______________________________________________________*/
  455.     GetGWorld (&SavePort, &SaveGD);
  456.     mycolors = GetCTable (clutID);
  457.     (*mycolors)->ctFlags |= 0x4000;
  458.  
  459.     myWindow = NewCWindow(nil, &BaseRect, "", TRUE, zoomDocProc, 
  460.                             (WindowPtr) -1, TRUE, 150);
  461.     SetGWorld((CGrafPtr)myWindow, SaveGD);
  462.     DrawGrowIcon (myWindow);
  463.  
  464.     srcPalette = NewPalette (numcolor, mycolors, pmCourteous, 0);
  465.     SetInhibited(pmCourteous);
  466.     SetPalette ((WindowPtr) myWindow, srcPalette, TRUE);
  467.     
  468.     DrawPicture (ThePict, &InitWindowSize);
  469.  
  470.     GetGWorld (&SavePort, &SaveGD);
  471.     err = NewGWorld (&offscreenGWorld, 8, &InitWindowSize, mycolors, nil, nil);
  472.     if (err)
  473.         Debugger();
  474.     SetGWorld (offscreenGWorld, nil);
  475.     EraseRect (&InitWindowSize);
  476.     DrawPicture (ThePict, &InitWindowSize);
  477.     SetGWorld (SavePort, SaveGD);        
  478.  
  479. /*______________________________________________________*/
  480. /*                    Set menus                         */
  481. /*______________________________________________________*/
  482.     mymenu0 = GetMenu(appleID);
  483.     AppendResMenu(mymenu0, 'DRVR');
  484.     InsertMenu(mymenu0,0);
  485.     mymenu1 = GetMenu(129);
  486.     InsertMenu(mymenu1,0);
  487.     mymenu2 = GetMenu(130);
  488.     InsertMenu(mymenu2,0);
  489.     DrawMenuBar();
  490.  
  491. /*______________________________________________________*/
  492. /*                  Set Up Sound                        */
  493. /*______________________________________________________*/
  494.  
  495.     SoundData = GetResource ('snd ', 100);
  496.     if (ResError() != noErr || SoundData == nil)
  497.         Debugger();
  498.     HLock (SoundData);
  499.     SoundSetUp();
  500.     }
  501.     
  502.     return;
  503. }
  504.  
  505. main()
  506. {
  507.     char            key;
  508.     Boolean            track;
  509.     long            growResult;
  510.     EventRecord     myEvent;
  511.     WindowPtr        whichWindow;
  512.     int                yieldTime;
  513.     RGBColor        changecolor;
  514.     CTabHandle        StoreCTab;
  515.     short            Usage, Tolerance;
  516.     OSErr            err;
  517. /*______________________________________________________*/
  518. /*                   Main Event loop                    */
  519. /*______________________________________________________*/
  520.     init();
  521.     yieldTime = 0;
  522.     StoreCTab = GetCTable (clutID);
  523.     for ( ;; ) {
  524.         if (DoneFlag) {
  525.             ExitToShell();
  526.             }
  527.             
  528.         /* If the usage is set to animate than animate the colors one step for eash event loop */
  529.         GetEntryUsage(srcPalette, 1, &Usage, &Tolerance);
  530.         Usage &= 0x0004;
  531.         if (Usage == 0x0004) {
  532.             err = SndChannelStatus (chan, sizeof (Stats), &Stats);
  533.             if (err != noErr)
  534.                 Debugger();
  535.             if (!Stats.scChannelBusy) {
  536.                 err = SndDisposeChannel (chan,FALSE);
  537.                 if (err != noErr)
  538.                     Debugger();
  539.         
  540.                 SoundSetUp();
  541.                 SoundOff();
  542.                 }
  543.             GetEntryColor (srcPalette, 1, &changecolor);
  544.             AnimatePalette (myWindow, StoreCTab, 2, 1, numcolor - 2);
  545.             AnimateEntry (myWindow, numcolor - 1, &changecolor);
  546.             Palette2CTab (srcPalette, StoreCTab);
  547.             }
  548.             
  549.         if (WaitNextEvent(everyEvent, &myEvent, yieldTime, nil)) {
  550.             switch (myEvent.what) {
  551.                 case mouseDown:
  552.                     switch (FindWindow(myEvent.where, &whichWindow)) {
  553.                         case inSysWindow:
  554.                             SystemClick(&myEvent, whichWindow);
  555.                             break;
  556.                         case inMenuBar:
  557.                             doCommand(MenuSelect(myEvent.where));
  558.                             break;
  559.                         case inContent:
  560.                             break;
  561.                         case inDrag:
  562.                             DragWindow (whichWindow, myEvent.where, &TotalRect);
  563.                             Draw();
  564.                             DrawGrowIcon (whichWindow);
  565.                             break;
  566.                         case inGrow:
  567.                             growResult = GrowWindow (whichWindow, myEvent.where,
  568.                                                     &minRect);
  569.                             SizeWindow(whichWindow, LoWord(growResult), 
  570.                                     HiWord(growResult), TRUE);
  571.                             EraseRect(&whichWindow->portRect);
  572.                             SetRect(&WinMinusScroll, whichWindow->portRect.left, 
  573.                                     whichWindow->portRect.top, 
  574.                                     whichWindow->portRect.right-20, 
  575.                                     whichWindow->portRect.bottom - 20);
  576.                             Draw();
  577.                             DrawGrowIcon (whichWindow);
  578.                             break;
  579.                         case inGoAway:
  580.                             track = TrackGoAway (whichWindow, myEvent.where);
  581.                             if (track) {
  582.                                 CloseWindow (whichWindow);
  583.                                 DoneFlag = TRUE;
  584.                                 }
  585.                             break;
  586.                         case inZoomIn:
  587.                             track = TrackBox (whichWindow, myEvent.where, inZoomIn);
  588.                             if (track) {
  589.                                 ZoomWindow (whichWindow, inZoomIn, TRUE);
  590.                                 EraseRect(&whichWindow->portRect);
  591.                                 SetRect(&WinMinusScroll, whichWindow->portRect.left, 
  592.                                         whichWindow->portRect.top, 
  593.                                         whichWindow->portRect.right-20, 
  594.                                         whichWindow->portRect.bottom - 20);
  595.                                 Draw();
  596.                                 DrawGrowIcon (whichWindow);
  597.                                 }
  598.                             break;
  599.                         case inZoomOut:
  600.                             track = TrackBox (whichWindow, myEvent.where, inZoomOut);
  601.                             if (track) {
  602.                                 ZoomWindow (whichWindow, inZoomOut, TRUE);
  603.                                 EraseRect(&whichWindow->portRect);
  604.                                 SetRect(&WinMinusScroll, whichWindow->portRect.left, 
  605.                                         whichWindow->portRect.top, 
  606.                                         whichWindow->portRect.right-20, 
  607.                                         whichWindow->portRect.bottom - 20);
  608.                                 Draw();
  609.                                 DrawGrowIcon (whichWindow);
  610.                                 }
  611.                             break;
  612.                         default:
  613.                             break;
  614.                         }
  615.                     break;
  616.                 case keyDown:
  617.                 case autoKey:
  618.                     key = myEvent.message & charCodeMask;
  619.                     if ( myEvent.modifiers & cmdKey )
  620.                         if ( myEvent.what == keyDown )
  621.                             doCommand(MenuKey(key));
  622.                     break;
  623.                 case updateEvt:
  624.                     if ((WindowPtr) myEvent.message == myWindow) {
  625.                         BeginUpdate((WindowPtr) myWindow);
  626.                         EndUpdate((WindowPtr) myWindow);
  627.                         Draw();
  628.                         }
  629.                     break;
  630.                 case diskEvt:
  631.                     break;
  632.                 case activateEvt:
  633.                     break;
  634.                 case app4Evt:
  635.                     if ((myEvent.message << 31) == 0) { /* Suspend */
  636.                         yieldTime = 30;
  637.                         HideWindow((WindowPtr) myWindow);
  638.                         }
  639.                     else { /* Resume */
  640.                         yieldTime = 0;
  641.                         ShowWindow((WindowPtr) myWindow);
  642.                         SetPort((WindowPtr) myWindow);
  643.                         }
  644.                     break;
  645.                 default:
  646.                     break;
  647.                 }
  648.             }
  649.         }
  650. }